﻿using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

namespace AMVInfoSpace
{
    /// <summary> Инфо для одного AMV </summary>
    public class AMVInfo : IComparable<AMVInfo>
    {
        /// <summary>Сайт</summary>
        public SITE Site;
        /// <summary>Номер AMV на сайте</summary>
        public int Number;

        public string Name;
        /// <summary>Список музыки</summary>
        public List<string> Msc = new List<string>();
        /// <summary>Список аниме</summary>
        public List<string> Anm = new List<string>();
        /// <summary>Список авторов</summary>
        public List<string> Atr = new List<string>();

        /// <summary>Список жанров</summary>
        public List<string> TagGenre = new List<string>();
        /// <summary>Список прочих тегов</summary>
        public List<string> TagOther = new List<string>();

        /// <summary>Список ключеных слов</summary>
        public List<string> Kwd = new List<string>();
        /// <summary>Список наград</summary>
        public List<string> Awd = new List<string>();
        /// <summary>Комментарий</summary>
        public string Comment;
        /// <summary>Рейтинг на момент граба страницы</summary>
        public decimal Rating = 0;
        /// <summary>Дата создания или публикации</summary>
        public DateTime CreateDate = DateTime.MinValue;
        /// <summary>Дата добавления на сайт</summary>
        public DateTime AppenedDate = DateTime.MinValue;
        /// <summary>Дата получения данных с сайта</summary>
        public DateTime GrabDate = DateTime.MinValue;

        #region *** для поиска совпадений при редактировании в AMVCommander'е *********
        public List<string> slName = new List<string>();
        public List<List<string>> slAtr = new List<List<string>>();
        public List<List<string>> slMsc = new List<List<string>>();
        public List<List<string>> slAnm = new List<List<string>>();

        // величина совпадений (для поиска в AMVCommander'е)
        public double c_conformity = 0;
        public double c_Name = 0;
        public double c_Msc = 0;
        public double c_Atr = 0;
        public double c_Anm = 0;
        public bool IsBind = false; // привязана к записи в базе
        #endregion *** для поиска совпадений при редактировании в AMVCommander'е *********

        /// <summary>Для отображения в списках</summary>
        public System.Windows.Forms.ListViewItem Itm = null;
        /// <summary>Локальное AMV (для отображения и быстрого доступа)</summary>
        public int LocalAMVInd = -1;
        /// <summary>Посмотренно</summary>
        public bool Watched = false;

        public AMVInfo(int Number, string Name, SITE Site)
        {
            this.Number = Number;
            this.Name = Name;
            this.Site = Site;
        }

        public AMVInfo(BinaryReader br)
        {
            // задел на версионность
            br.ReadInt32();

            Number = br.ReadInt32();
            Name = br.ReadString();
            Site = (SITE)br.ReadInt32();
            Rating = br.ReadDecimal();

            int kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                Msc.Add(br.ReadString());

            kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                Anm.Add(br.ReadString());

            kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                Atr.Add(br.ReadString());

            kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                TagGenre.Add(br.ReadString());

            kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                TagOther.Add(br.ReadString());

            kolvo1 = br.ReadInt32();
            for (int j = 0; j < kolvo1; j++)
                Awd.Add(br.ReadString());

            Comment = br.ReadString();
            CreateDate = new DateTime(br.ReadInt64());
            AppenedDate = new DateTime(br.ReadInt64());
            GrabDate = new DateTime(br.ReadInt64());
        }

        public void Save(BinaryWriter bw)
        {
            // версия
            bw.Write(0);

            bw.Write(Number);
            bw.Write(Name);
            bw.Write((int)Site);
            bw.Write(Rating);

            bw.Write(Msc.Count);
            for (int j = 0; j < Msc.Count; j++)
                bw.Write(Msc[j]);

            bw.Write(Anm.Count);
            for (int j = 0; j < Anm.Count; j++)
                bw.Write(Anm[j]);

            bw.Write(Atr.Count);
            for (int j = 0; j < Atr.Count; j++)
                bw.Write(Atr[j]);

            bw.Write(TagGenre.Count);
            for (int j = 0; j < TagGenre.Count; j++)
                bw.Write(TagGenre[j]);

            bw.Write(TagOther.Count);
            for (int j = 0; j < TagOther.Count; j++)
                bw.Write(TagOther[j]);

            bw.Write(Awd.Count);
            for (int j = 0; j < Awd.Count; j++)
                bw.Write(Awd[j]);

            bw.Write(Comment);
            bw.Write(CreateDate.Ticks);
            bw.Write(AppenedDate.Ticks);
            bw.Write(GrabDate.Ticks);
        }

        public void SetFindInfo()
        {
            #region *** заполнение массивов для сравнения ***
            slName = SplitTextForFind(Name);
            for (int m = 0; m < Atr.Count; m++)
            {
                List<string> l = new List<string>();
                List<string> sl = SplitTextForFind(Atr[m]);
                for (int m1 = 0; m1 < sl.Count; m1++)
                    l.Add(sl[m1]);
                slAtr.Add(l);
            }
            for (int m = 0; m < Msc.Count; m++)
            {
                List<string> l = new List<string>();
                List<string> sl = SplitTextForFind(Msc[m]);
                for (int m1 = 0; m1 < sl.Count; m1++)
                    l.Add(sl[m1]);
                slMsc.Add(l);
            }
            for (int m = 0; m < Anm.Count; m++)
            {
                List<string> l = new List<string>();
                List<string> sl = SplitTextForFind(Anm[m]);
                for (int m1 = 0; m1 < sl.Count; m1++)
                    l.Add(sl[m1]);
                slAnm.Add(l);
            }
            #endregion *** заполнение массивов для сравнения ***
        }

        /// <summary>разбивка на слова. Слова состоят только из букв и цифр. Остальное считается разделителем. Слова приводятся к верхнему регистру
        /// слова только длиной > 1 буквы</summary>
        public static List<string> SplitTextForFind(string s)
        {
            List<string> ret = new List<string>();
            for (int i = 0; i < s.Length; i++)
            {
                int n = (int)s[i];
                if ((n < 48 || (n > 57 && n < 65) || (n > 90 && n < 97) || (n > 122 && n < 1040) || (n > 1103)) && n != 1025 && n != 1105)
                    s = s.Replace(s[i], ' ');
            }
            string[] sl = s.Split(' ');
            for (int i = 0; i < sl.Length; i++)
            {
                if (sl[i].Trim() != "")
                {
                    if (sl[i].Trim().Length > 1)
                        ret.Add(sl[i].Trim().ToUpper());
                }
            }
            return ret;
        }

        public static bool SortDesc = false;
        public enum SortMODE { C_CONFORMITY, Name, Rating, Site, }
        public static SortMODE SortMode = SortMODE.C_CONFORMITY;
        public int CompareTo(AMVInfo fa)
        {
            int ret;
            ret = c_conformity.CompareTo(fa.c_conformity);
            switch (SortMode)
            {
                case SortMODE.Name: ret = Name.CompareTo(fa.Name); break;
                case SortMODE.Rating: ret = Rating.CompareTo(fa.Rating); break;
                case SortMODE.Site: ret = Site.CompareTo(fa.Site); break;
            }
            if (SortDesc) ret *= -1;
            return ret;
        }
    }
}
